package com.ling.config;

import com.fasterxml.jackson.databind.JavaType;
import com.ling.pl.core.commons.exception.BusinessException;
import com.ling.pl.core.commons.springmvc.ResposeInfo;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.json.MappingJacksonInputMessage;

import java.io.IOException;
import java.lang.reflect.Type;

/**
 * Created by bo.wang on 2017/4/9.
 */
public class ResposeInfoHttpMessageConverter extends MappingJackson2HttpMessageConverter {

    @Override
    public Object read(Type type, Class<?> contextClass, HttpInputMessage inputMessage)
            throws IOException, HttpMessageNotReadableException {
        try {
            JavaType javaType = getJavaType(ResposeInfo.class, contextClass);
            ResposeInfo resposeInfo = (ResposeInfo) readJavaType(javaType, inputMessage);
            if (resposeInfo.isSuccess()) {
                return resposeInfo.getData();
            } else {
                throw new BusinessException(resposeInfo.getMessage());
            }
        } catch (BusinessException e) {
            ///todo 这里没有反映真实的异常 需要处理HystrixBadRequestException(可避开circuit breaker的统计)
            throw new BusinessException(e.getMessage());
        } catch (Exception e) {
            JavaType javaType = getJavaType(type, contextClass);
            return readJavaType(javaType, inputMessage);
        }
    }

    private Object readJavaType(JavaType javaType, HttpInputMessage inputMessage) {
        try {
            if (inputMessage instanceof MappingJacksonInputMessage) {
                Class<?> deserializationView = ((MappingJacksonInputMessage) inputMessage).getDeserializationView();
                if (deserializationView != null) {
                    return this.objectMapper.readerWithView(deserializationView).forType(javaType).
                            readValue(inputMessage.getBody());
                }
            }
            return this.objectMapper.readValue(inputMessage.getBody(), javaType);
        } catch (IOException ex) {
            throw new HttpMessageNotReadableException("Could not read document: " + ex.getMessage(), ex);
        }
    }
}